package com.dbflow5.adapter.queriable;

import com.dbflow5.adapter.CacheAdapter;
import com.dbflow5.adapter.ModelAdapter;
import com.dbflow5.database.DatabaseWrapper;
import com.dbflow5.database.FlowCursor;
import com.dbflow5.query.cache.ModelCache;

/**
 * Description: Loads model data that is backed by a [ModelCache]. Used when [Table.cachingEnabled]
 * is true.
 */
public class CacheableModelLoader<T> extends SingleModelLoader<T>{

    protected CacheAdapter<T> cacheAdapter;
    protected ModelAdapter<T> modelAdapter;

    protected ModelCache<T, ?> modelCache;

    public CacheableModelLoader(Class<T> modelClass, CacheAdapter<T> cacheAdapter){
        super(modelClass);
        this.cacheAdapter = cacheAdapter;
        modelAdapter = getModelAdapter();
        modelCache = cacheAdapter.modelCache;
    }

    private ModelAdapter<T> getModelAdapter(){
        if(getInstanceAdapter() instanceof ModelAdapter){
            ModelAdapter<T> modelAdapter = (ModelAdapter<T>)getInstanceAdapter();
            if (!modelAdapter.cachingEnabled()) {
                throw new IllegalArgumentException(("You cannot call this method for a table that or has no caching id " +
                        "or use one Primary Key " +
                        "or use the MultiCacheKeyConverter").trim());
            }
            return modelAdapter;
        }else {
            throw new IllegalArgumentException("A non-Table type was used.");
        }
    }

    /**
     * Converts data by loading from cache based on its sequence of caching ids. Will reuse the passed
     * [T] if it's not found in the cache and non-null.
     *
     * @param cursor cursor
     * @param moveToFirst moveToFirst
     * @param databaseWrapper databaseWrapper
     * @return A model from cache.
     */
    @Override
    public T convertToData(FlowCursor cursor, boolean moveToFirst, DatabaseWrapper databaseWrapper) {
        if (!moveToFirst || cursor.goToFirstRow()) {
            Object[] values = cacheAdapter.getCachingColumnValuesFromCursor(new Object[cacheAdapter.cachingColumnSize], cursor);
            return ModelCache.addOrReload(modelCache, cacheAdapter.getCachingId(values), cacheAdapter, modelAdapter, cursor, databaseWrapper);
        }
        return null;
    }
}
